/*
===========================================================================
Copyright (C) 2013-2014 Avotu Briezhaudzetava

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.

===========================================================================
*/

//
// includes
//
#include "gui_main.h"
#include "ui_gui_main.h"
#include "gui_precursors.h"
#include <QMessageBox>
#include <math.h>
#include "gui_license.h"
#include "gui_users.h"

/*
================
construct
================
*/
Gui_Main::Gui_Main( QWidget *parent ) : QMainWindow( parent ), ui( new Ui::Gui_Main ) {
    ui->setupUi( this );
    this->connect( this->ui->widgetAddEdit, SIGNAL( visibilityChanged( bool )), this, SLOT( toggleWidgetVisibility( bool )));
    this->connect( this->ui->comboPrecursors, SIGNAL( currentIndexChanged( int )), this, SLOT( fillLogs()));
    this->connect( &m, SIGNAL( logListChanged()), this, SLOT( fillLogs()));
    this->setLastIndex();
    this->setUnlocked();
}

/*
================
initialize
================
*/
void Gui_Main::initialize() {
    this->toggleWidgetState();
    this->fillPrecursors();

    // set up view
    this->tableModel = new LogTableModel();
    this->ui->tableEntries->setModel( this->tableModel );
}

/*
================
fillPrecursors
================
*/
void Gui_Main::fillPrecursors() {
    this->setLocked();
    this->ui->comboPrecursors->clear();

    foreach ( PrecursorEntry *pPtr, m.precursorList ) {
        if ( pPtr->isSolvent())
            this->ui->comboPrecursors->addItem(
                    QString( "%1 (%2 g/cm3)" ).arg( pPtr->title()).arg( pPtr->density()),
                    m.precursorList.indexOf( pPtr ));
        else
            this->ui->comboPrecursors->addItem( pPtr->title(), m.precursorList.indexOf( pPtr ));
    }

    // restore index
    if ( this->lastIndex() != -1 && this->lastIndex() < this->ui->comboPrecursors->count())
        this->ui->comboPrecursors->setCurrentIndex( this->lastIndex());
    this->setUnlocked();

    // refresh logs
    this->fillLogs();
}

/*
================
fillUnits
================
*/
void Gui_Main::fillUnits() {
    PrecursorEntry *pPtr;

    // failsafe
    if ( m.precursorList.isEmpty())
        return;

    // find precursor, fill correct units
    pPtr = m.precursorForId( m.precursorList.at( this->ui->comboPrecursors->currentIndex())->id());
    if ( pPtr != NULL ) {
        m.fillUnits( this->ui->comboUnits, pPtr->isSolvent());

        // set default unit
        this->ui->comboUnits->setCurrentIndex( m.unitsToIndex( this->ui->comboUnits, pPtr->units()));
    }
}

/*
================
fillLogs
================
*/
void Gui_Main::fillLogs() {
    if ( m.precursorList.isEmpty() /*&& this->ui->comboPrecursors->count() != 0*/)
        return;

    // begin reset
    if ( this->tableModel != NULL && this->ui->tableEntries->model() != NULL )
        this->tableModel->beginReset();

    // get a valid index and refresh logs
    if ( this->ui->comboPrecursors->currentIndex() == -1 )
        m.filterLogs( m.precursorList.first()->id());
    else
        m.filterLogs( m.precursorList.at( this->ui->comboPrecursors->currentIndex())->id());

    // end reset
    if ( this->tableModel != NULL && this->ui->tableEntries->model() != NULL )
        this->tableModel->endReset();
}

/*
================
toggleWidgetVisibility
================
*/
void Gui_Main::toggleWidgetVisibility( bool visible ) {
    if ( visible ) {
        this->ui->widgetAddEdit->setEnabled( true );
        this->ui->widgetAddEdit->show();
        this->ui->buttonAdd->setDisabled( true );
        this->ui->buttonEdit->setDisabled( true );
        this->ui->buttonRemove->setDisabled( true );
        this->ui->tableEntries->setDisabled( true );
        this->clearItemState();
    } else {
        this->ui->widgetAddEdit->setDisabled( true );
        this->ui->widgetAddEdit->hide();
        this->ui->buttonAdd->setEnabled( true );
        this->ui->buttonEdit->setEnabled( true );
        this->ui->buttonRemove->setEnabled( true );
        this->ui->tableEntries->setEnabled( true );
    }
}

/*
================
toggleWidgetState
================
*/
void Gui_Main::toggleWidgetState( State state ) {
    this->m_state = state;

    switch ( state ) {
    case Add:
        this->toggleWidgetVisibility();
        this->fillUnits();
        this->ui->buttonAccept->setFocus();
        break;

    case Edit:
        this->toggleWidgetVisibility();
        this->fillUnits();
        this->readItemState();
        this->ui->buttonAccept->setFocus();
        break;

    case NoState:
    default:
        this->toggleWidgetVisibility( false );
        //this->clearItemState();
        this->ui->buttonAdd->setFocus();
        break;
    }
}

/*
================
destruct
================
*/
Gui_Main::~Gui_Main() {
    this->disconnect( this->ui->widgetAddEdit, SIGNAL( visibilityChanged( bool )));
    this->disconnect( &m, SIGNAL( logListChanged()));
    this->disconnect( this->ui->comboPrecursors, SIGNAL( currentIndexChanged( int )));
    delete this->tableModel;
    delete ui;
}

/*
================
buttonAccept->clicked
================
*/
void Gui_Main::on_buttonAccept_clicked() {
    float amount = this->ui->spinboxAmount->value();

    // failsafe - amount
    if ( amount == 0.0f ) {
        QMessageBox::warning( this, this->tr( "Add precursor log" ),
                                    this->tr( "Please specify amount" ), QMessageBox::Ok );
        return;
    }

    // failsafe - purpose
    if ( this->ui->textPurpose->text().isEmpty()) {
        QMessageBox::warning( this, this->tr( "Add precursor log" ),
                                    this->tr( "Please specify purpose" ), QMessageBox::Ok );
        return;
    }

    // all ok - proceed!
    this->saveItemState();
    this->toggleWidgetState();
}

/*
================
saveItemState
================
*/
void Gui_Main::saveItemState() {
    this->tableModel->beginReset();
    float amount = this->ui->spinboxAmount->value();

    // make sure we make it negative
    if ( !this->ui->checkRestock->isChecked())
        amount *= -1.0f;

    if ( this->currentState() == Add ) {
        // finally add log
        m.addLog( m.precursorList.at( this->ui->comboPrecursors->currentIndex())->id(),
                  0,
                  amount,
                  this->ui->dateEdit->dateTime().toString( Qt::TextDate ),
                  this->ui->textPurpose->text(),
                  m.indexToUnits( this->ui->comboUnits )
                  );
    } else if ( this->currentState() == Edit ) {
        LogEntry *lPtr;

        // get current log
        lPtr = m.logForId( this->ui->tableEntries->model()->data( this->ui->tableEntries->currentIndex(), Qt::UserRole ).toInt());
        if ( lPtr == NULL )
            return;

        // set values
        /* TODO: user, template */
        lPtr->setUnits( Main::indexToUnits( this->ui->comboUnits ));
        lPtr->setPurpose( this->ui->textPurpose->text());
        lPtr->setAmount( amount );
        lPtr->setDateTime( this->ui->dateEdit->dateTime());
    }

    this->tableModel->endReset();
}


/*
================
actionPrecursors->triggered
================
*/
void Gui_Main::on_actionPrecursors_triggered() {
    Gui_Precursors pDialog( this );
    pDialog.exec();
    this->fillPrecursors();
}

/*
================
buttonRemove->clicked
================
*/
void Gui_Main::on_buttonRemove_clicked() {
    m.removeLog( this->ui->tableEntries->model()->data( this->ui->tableEntries->currentIndex(), Qt::UserRole ).toInt());
}

/*
================
clearItemState
================
*/
void Gui_Main::clearItemState() {
    // clear everything
    this->ui->comboTemplate->clear();
    this->ui->comboUsers->clear();
    this->ui->textPurpose->clear();
    this->ui->checkRestock->setChecked( false );
    this->ui->spinboxAmount->setValue( 0.0f );
    this->ui->dateEdit->setDateTime( QDateTime::currentDateTime());
    this->ui->comboUnits->clear();
}

/*
================
readItemState
================
*/
void Gui_Main::readItemState() {
    LogEntry *lPtr;

    // available only in edit mode
    if ( this->currentState() != Edit )
        return;

    // get current log
    lPtr = m.logForId( this->ui->tableEntries->model()->data( this->ui->tableEntries->currentIndex(), Qt::UserRole ).toInt());
    if ( lPtr == NULL )
        return;

    // set values
    /* TODO: user, template */
    this->ui->comboUnits->setCurrentIndex( Main::unitsToIndex( this->ui->comboUnits, lPtr->units()));
    this->ui->textPurpose->setText( lPtr->purpose());
    this->ui->spinboxAmount->setValue( fabs( lPtr->amount()));
    if ( lPtr->amount() > 0 )
        this->ui->checkRestock->setChecked( true );
    this->ui->dateEdit->setDateTime( lPtr->dateTime());
}

/*
================
actionAbout->triggered
================
*/
void Gui_Main::on_actionAbout_triggered() {
    Gui_License license( this );
    license.exec();
}

/*
================
actionUsers->triggered
================
*/
void Gui_Main::on_actionUsers_triggered() {
    Gui_Users users( this );
    users.exec();
}
